package pacman.level;

import java.util.Iterator;
import java.util.Vector;

import org.newdawn.slick.AngelCodeFont;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.state.BasicGameState;

import pacman.actors.Ghost;
import pacman.base.Entity;
import pacman.base.Entity.Role;
import pacman.base.Level;
import pacman.base.Score;
import pacman.map.Map;
import pacman.util.Clock;

public class SimpleLevel implements Level {
    private Vector<Entity> entities;			//Giống như ArrayList nhưng nó sẽ là Thread Safe
    private Map map;							//Tiled Map của mỗi Level
    private boolean levelEnded = false;			//Kiểm tra trạng thái Game, hoàn thành hay chưa
    private boolean levelLose = false;			//Kiểm tra trạng thái Game, thua hay chưa
    private AngelCodeFont font;					//Font chữ của Game
    private Image box;							//Ô bảng để in điểm và thời gian chơi trên này.
    private static Clock clock;					//Đồng hồ để tính thời gian, chạy theo hàm Update
    /**
     * Constructor của một SimpleLevel
     * @param mapPath Đường dẫn đến map tương ứng, được lưu trong HashTable
     */
    public SimpleLevel(String mapPath) {
		try {
		    box = new Image("data/roundBox.png");								//Load hình vẽ cái khung in điểm, thời gian
		    font = new AngelCodeFont("data/demo2.fnt", "data/demo2_00.tga");	//Load Font chữ
		} catch (Exception e) {
	    	System.out.println(e.getMessage());
	    }	
		entities = new Vector<Entity>();										//Tạo một Array Entity trống
		try {
		    map = new Map(mapPath);												//Load Map tương ứng
		} catch (Exception e) {
	    	System.out.println(e.getMessage());
	    }
		add(map);																//Vì map cũng là một Entity, add vào entities
		map.addToLevel(this);													//Add mọi entity lấy được từ Map vào Vector<Entity>
		clock = new Clock();													//Tạo một đồng hồ để in thời gian
	    }
	
    public void render(BasicGameState bgs, Graphics g) {
		for (Entity e : entities) {
		    e.render(bgs, g);													//Với mọi Entities thu được thì sẽ in ra màn hình
		}																		//từ hàm render của Game State
		box.draw(0, 0);															//Vẽ Khung in điểm và thời gian vào góc bên trái
		font.drawString(10, 10, "Score: " + Score.getScore());					//Lấy số điểm hiện tại
		font.drawString(10, 40, "Time : " + Clock.getTime());					//Lấy thời gian đã chơi
		box.draw(0, 550);														//Vẽ Thêm một khung ở góc dưới bên trái để in ra số mạng còn lại
		font.drawString(10, 560, "Lives : " + Map.getPlayer().getLive());		//Load Player hiện tại của map và lấy thông tin về số mạng còn lại
    }
    
    public void update(GameContainer gc, int delta) {
		for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
		    Entity ent = iterator.next();										//Với mỗi Entity trong entities thì sẽ update
		    ent.update(gc, delta);												//Hàm này được gọi trong hàm update của Game State	
		}
		removeEntities();														//Loại bỏ những entites có thể xóa, tức là ko render nữa
		isLevelWon();															//Kiểm tra thắng chưa
		isLevelLosed();															//Kiểm tra thua chưa
		Score.setScore(Map.getPlayer().getScore());								//Set điểm mới của người chơi
		clock.update(delta);													//Update đồng hồ
		Score.setTime(Clock.getTimer());										//Set thời gian để tính bonus điểm
    }
    public void add(Entity e) {
		entities.add(e);														//Thêm một Entity vào entites
    }

    public void clear() {														//Clear tất cả mọi thứ bên trong một level
    	for (int i = 0; i < entities.size(); i++) {
		    entities.get(i).removeFromLevel(this);
		    entities.remove(i);
		}
    }

    public void remove(Entity e) {
    	entities.remove(e);														//Xóa một entity trong level
    }  
    
    public boolean isLevelEnded() {
    	return levelEnded;														//Kiểm tra một level xong chưa
    }

    public boolean isLevelLose() {
    	return levelLose;														//Thua chưa
    }

    private void isLevelWon() {
	    int gemLeft = 0;														//Game hoàn thành khi tất cả các hạt trên map đc ăn hết
		for (Iterator<Entity> iterator = entities.iterator(); iterator .hasNext();) {
		    Entity ent = iterator.next();
		    if(ent.getRole().equals(Entity.Role.GOLD)) {						//Nếu có entity nào có role là GOLD thì tức là chưa hoàn thành
		    	gemLeft++;
		    }
		}
		if (gemLeft == 0) {
		    levelEnded = true;													//Nếu không có tức là win 1 level
		}
    }
    
    private void isLevelLosed() {
		boolean playerFound = false;															//Nếu không Player Entity thì tức là thua :D
		for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
		    Entity ent = iterator.next();
		    if (ent.getRole().equals(Entity.Role.PLAYER)) playerFound = true;
		}
		if (!playerFound)  levelLose = true;
    }

    private void removeEntities() {
		Vector<Entity> removeable = new Vector<Entity>();
		for (Iterator<Entity> iterator = entities.iterator(); iterator .hasNext();) {
		    Entity ent = iterator.next();
		    if (ent.isToRemove()) {																//Nếu Entity được đánh dấu xóa
				removeable.add(ent);															//Add vào array Removeable
				if (ent.getRole().equals(Role.EATGEM)) alertGhostsEatable();					//Đánh thức Ghost
		    }
		}
		entities.removeAll(removeable);															//Remove tất cả các entities có trong Removeable
    }

    public void alertGhostsEatable() {
		for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
		    Entity ent = iterator.next();
		    if (ent.getRole().equals(Role.GHOST)) {												//Tìm Entity có role là Ghost
				Ghost gh = (Ghost) ent;															
				if (!gh.getState().equals(Ghost.State.DEATH)) {									//Nếu chưa chết
				    gh.setEatable();															//thì Eable
				}
		    }
		}
    }
}
